package com.atguigu.gmall.realtime.app.marketing.func;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.atguigu.gmall.realtime.app.marketing.bean.MarketingRuleAllInfo;
import com.atguigu.gmall.realtime.utils.JdbcUtil;
import com.atguigu.gmall.realtime.utils.MySqlUtil;
import com.atguigu.gmall.realtime.utils.RedisUtil;
import org.roaringbitmap.RoaringBitmap;
import org.roaringbitmap.longlong.Roaring64Bitmap;
import redis.clients.jedis.Jedis;

import java.sql.Connection;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

public class RuleFetcher {

    Connection connection;

    Jedis jedis;
    public RuleFetcher(Connection connection, Jedis jedis ){
        this.connection=connection;
        this.jedis=jedis;
    }



    List<MarketingRuleAllInfo> fetch(){
        // 通过jdbc实现一个sql的list查询
       // 构造一个jdbc工具 查询mysql
        String sql=" select  mr.id, " +
                " mt.trigger_event," +
                "  mg.group_ids_json,mg.user_actions_today_json ," +
                " mc.channel_type , mc.limit_time_num,mc.limit_time_unit, " +
                " mcm.model_title, mcm.model_text,mcm.url " +
                " from marketing_rule mr " +
                " inner join  marketing_rule_time mt  on mr.id= mt.marketing_rule_id " +
                " inner join  marketing_rule_group mg  on mr.id= mg.marketing_rule_id " +
                " inner join  marketing_rule_channel mc on mr.id= mc.marketing_rule_id " +
                " inner join  marketing_rule_channel_model mcm  on mcm.id= mc.channel_model_id " +
                " where  is_enable='1'  and  (from_dt is null or from_dt <= now() )  and  (to_dt is null or to_dt >= now())" +
                " and push_type='3'" ;
        // 条件 1 已启用  2 在时效范围内 3 push_type =3

        List<MarketingRuleAllInfo>  ruleAllInfoList= new ArrayList<>();
        try {
            ruleAllInfoList= JdbcUtil.queryList(connection,sql,MarketingRuleAllInfo.class,true);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        for (MarketingRuleAllInfo marketingRuleAllInfo : ruleAllInfoList) {
            //把groudIdsJson转换为人群集合
            RoaringBitmap userGroupBitmap = getUserGroup(marketingRuleAllInfo.getGroupIdsJson());
            marketingRuleAllInfo.setUserGroupBitmap(userGroupBitmap);
            // 把用户行为json转为List
            List<JSONObject> userActionList = JSON.parseArray(marketingRuleAllInfo.getUserActionsTodayJson(), JSONObject.class);
            marketingRuleAllInfo.setUserActionList(userActionList);

        }

      //  System.out.println(" 查询规则: "+ruleAllInfoList);
        return ruleAllInfoList;
     }

     //把分群json 转为一个人群bitmap
     private  RoaringBitmap  getUserGroup(String groupIdsJson){
        // 不只一个分群  多个分群    分群之间   并集 利用redis求  sunion  取分群并集
         // 1  把json转换为 分群id集合
         List<String> groupIdsList = JSON.parseArray(groupIdsJson, String.class);
         // 2  把分群id集合 利用 redis求并集
         String[] groupIdsArr= groupIdsList.stream().map( groupId->"user_group:"+groupId).toArray( String[]::new);

         Set<String> uidSet = jedis.sunion(groupIdsArr);
         // 3 把并集结果保存在一个内存对象中 ？  用什么java 结构？ list
         //groupIds.contains()
         //把 Set<String> 变为 int[]
         int[] uidArr = uidSet.stream().mapToInt(uid -> Integer.valueOf(uid)).toArray();

         RoaringBitmap roaringBitmap = new RoaringBitmap();
         roaringBitmap.add(uidArr);//写入
         // 这个内存对象的使用场景？  判存 判断一个只是否在一个集合中
         //roaringBitmap.contains();//判存
         return roaringBitmap;
     }
}
